#include "core.h"

#include <QSettings>
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>

QString Core::m_rootPath;
QSettings *Core::m_settings;
Core *Core::m_instance;

Core *Core::instance()
{
    if (m_instance == nullptr)
    {
        m_instance = new Core();
    }
    return m_instance;
}

Core::Core()
{
    m_settings =  new QSettings(QSettings::IniFormat, QSettings::UserScope,
                                QCoreApplication::organizationName(),
                                QCoreApplication::applicationName());
}

QSettings *Core::settings()
{
    return instance()->m_settings;
}

QVersionNumber Core::version()
{
    return QVersionNumber(EDA_MAJOR_VERSION,
                          EDA_MINOR_VERSION,
                          EDA_RELEASE_VERSION);
}

QVersionNumber Core::compatibilityVersion()
{
    return QVersionNumber(EDA_COMPAT_MAJOR_VERSION,
                          EDA_COMPAT_MINOR_VERSION,
                          EDA_COMPAT_RELEASE_VERSION);
}

QString Core::sourceId()
{
    return  QString(CI_SOURCE_ID);
}

bool Core::sourceIdIsTainted()
{
    return CI_SOURCE_TAINTED;
}

QUrl Core::browsableSourceUrl()
{
    return QUrl(CI_SOURCE_URL);
}

QString Core::buildId()
{
    return  QString(CI_BUILD_ID);
}

// Taken from Qt Creator source code
// We could rely on QBS as well
QString Core::compilerId()
{
#if defined(Q_CC_CLANG) // must be before GNU, because clang claims to be GNU too
    QString isAppleString;
#if defined(__apple_build_version__) // Apple clang has other version numbers
    isAppleString = QLatin1String(" (Apple)");
#endif
    return QLatin1String("Clang " ) + QString::number(__clang_major__) + QLatin1Char('.')
            + QString::number(__clang_minor__) + isAppleString;
#elif defined(Q_CC_GNU)
    return QLatin1String("GCC " ) + QLatin1String(__VERSION__);
#elif defined(Q_CC_MSVC)
    if (_MSC_VER > 1999)
        return QLatin1String("MSVC <unknown>");
    if (_MSC_VER >= 1900) // 1900: MSVC 2015
        return QLatin1String("MSVC 2015");
    if (_MSC_VER >= 1800) // 1800: MSVC 2013 (yearly release cycle)
        return QLatin1String("MSVC ") + QString::number(2008 + ((_MSC_VER / 100) - 13));
    if (_MSC_VER >= 1500) // 1500: MSVC 2008, 1600: MSVC 2010, ... (2-year release cycle)
        return QLatin1String("MSVC ") + QString::number(2008 + 2 * ((_MSC_VER / 100) - 15));
    return QLatin1String("<unknown MSVC compiler>");
#else
    return QLatin1String("<unknown compiler>");
#endif
}

QDateTime Core::buildDateTime()
{
    return QDateTime::fromString(CI_DATETIME, Qt::ISODate);
}

QVersionNumber Core::qtVersion()
{
    // Build time
    return QVersionNumber::fromString(QLatin1String(QT_VERSION_STR));
}

QVersionNumber Core::qtCompatibilityVersion()
{
    // Run time
    return QVersionNumber::fromString(QLatin1String(qVersion()));
}

QString Core::sourcePath()
{
    return QString(EDA_SOURCE_PATH);
}

QString Core::rootPath()
{
    return m_rootPath;
}

QString Core::applicationPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_APP_PATH));
}

QString Core::binaryPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_BIN_PATH));
}

QString Core::libraryPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_LIB_PATH));
}

QString Core::privateBinaryPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_LIBEXEC_PATH));
}

QString Core::pluginPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_PLUGIN_PATH));
}

QString Core::dataPath(const QString &suffix)
{
    return QDir::cleanPath(QString("%1/%2%3")
                           .arg(rootPath())
                           .arg(EDA_DATA_PATH)
                           .arg(suffix));
}

QString Core::documentationPath()
{
    return QDir::cleanPath(QString("%1/%2")
                           .arg(rootPath())
                           .arg(EDA_DOC_PATH));
}

void Core::initialise(const QString &rootPath)
{
    if (rootPath.isNull())
    {
        m_rootPath = QDir::cleanPath(QString("%1/%2")
                                     .arg(QCoreApplication::applicationDirPath())
                                     .arg(EDA_RELATIVE_ROOT_PATH));
    }
    else
    {
        m_rootPath = rootPath;
    }
}

QIcon Core::icon(const QString &name)
{
    if (name.isEmpty())
        return QIcon();

    QIcon defaultIcon;
    QFileInfo fileInfo(QString(":/icons/%1.svg").arg(name));
    if (fileInfo.exists())
        defaultIcon = QIcon(fileInfo.filePath());
    return QIcon::fromTheme(name, defaultIcon);
}
